home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d20
/
msgq160s.arc
/
MAKEMSG.C
< prev
next >
Wrap
Text File
|
1991-10-26
|
22KB
|
968 lines
/*
* MAKEMSG.C - Create messages
*
* Msged/Q message editor for QuickBBS Copyright 1990 by P.J. Muller
*
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#include "msged.h"
#include "screen.h"
#include "qmsgbase.h"
#include <assert.h>
#define TEXTLEN 200
#define INPLEN 60
static void show_attrib(void);
static int change_from(void);
static int change_attrib(void);
static int change_to(void);
static int change_dest(void);
static int change_orig(void);
static int change_subject(void);
static void doquote(BOOLEAN otherarea);
/* static char work[TEXTLEN]; */
static int do_lookup = FALSE;
static void createmsg(void);
/*
* Initialise the global message fields
*/
static void createmsg()
{
memset(&(message.header), 0, sizeof(message.header));
message.header.msgnum = newmsgnum();
strncpy(message.header.from, username, sizeof(message.header.from));
timestr(message.header.posttime,message.header.postdate);
message.header.board = CurBoard;
memset(&message.to,0, sizeof(message.to));
memset(&message.from,0,sizeof(message.from));
#ifdef EIDS
memset(&message.eid,0,sizeof(message.eid));
#endif
memset(&message.msgid,0,sizeof(message.msgid));
message.header.origzone = message.header.destzone = thisnode[CurAKA].zone;
message.header.up = 0;
message.header.reply = 0;
clear_attributes(&message.header);
clearbuffer(&msgbuf);
message.to.zone = thisnode[CurAKA].zone;
message.to.domain = NULL;
message.from = thisnode[CurAKA];
if (message.from.domain != NULL)
message.from.domain = strdup(message.from.domain);
/* message.from.domain = NULL; */
} /* createmsg */
void newmsg()
{
int keep;
keep = curmsg(CurBoard);
createmsg();
editheader();
switch (editmsg()) {
case SAVE:
save(message);
break;
case ABORT:
break;
} /* switch */
setcur(CurBoard,keep);
} /* newmsg */
void reply()
{
char msgto[sizeof(message.header.to)];
char subject[sizeof(message.header.subj)];
int link;
ADDRESS tmp;
MSGHEADER hlink;
int t = curmsg(CurBoard);
memcpy(msgto, message.header.from, sizeof(message.header.to));
memcpy(subject, message.header.subj, sizeof(message.header.subj));
tmp = message.from;
link = message.header.msgnum;
createmsg();
/* do_lookup = FALSE; */
memcpy(message.header.to, msgto, sizeof(message.header.to));
memcpy(message.header.subj, subject, sizeof(message.header.subj));
message.to = tmp;
editheader();
message.header.reply = link;
switch (editmsg()) {
case SAVE:
readheader(link, &hlink);
hlink.up = message.header.msgnum;
writeheader(&hlink);
save(message);
break;
case ABORT:
break;
} /* switch */
setcur(CurBoard,t);
} /* reply */
void quote()
{
doquote(FALSE);
}
void quotemv()
{
doquote(TRUE);
}
/*
* Expand a quote string, return a malloc'ed pointer
* '*' is replaced with first initial
* '^' is replaced with last initial
* '&' is replaced with all the initials
*/
static char *expandquote(char *qs, char *name)
{
char init[11]; /* initials */
char exp[TEXTLEN]; /* expanded quote string */
char *tok, *t, *s, *i = init;
/* first parse the name */
t = s = strdup(name);
if ((t == NULL) || (qs == NULL)) return(NULL);
do {
tok = strtok(s,"._ \t\n\r");
s = NULL; /* for strtok(), keeps internal pointer */
if ((tok != NULL) && (isalpha(*tok)))
*i++ = *tok;
} while ((tok != NULL) && (i-init < 11));
*i = EOS;
ptrfree(t);
/* now expand the quote string */
t = exp;
s = qs;
while ((*s != EOS) && (t-exp < TEXTLEN)) {
switch (*s) {
case '*':
*t++ = init[0]; /* first initial */
s++; break;
case '^':
if (i-init > 1) /* more than one initial */
*t++ = *(i-1); /* last initial */
else
*t++ = '.'; /* else add a period */
s++; break;
case '&': /* all initials */
for (tok = init; *tok != EOS; tok++)
*t++ = *tok;
s++; break;
default:
*t++ = *s++;
} /* switch */
} /* while */
*t = EOS;
return(strdup(exp));
} /* expandquote */
/*
* Expand the attribution line
* Return a strdup'ed string
*/
static char *expandattrib(char *s, char *from, char *node, char *to, char *date)
{
char exp[TEXTLEN];
char *t = exp;
while ((*s != EOS) && (t-exp < TEXTLEN-2)) {
if (*s == '$') {
char *ts;
switch (*(++s)) {
case 'd':
ts = date; break;
case 'f':
ts = from; break;
case 't':
ts = to; break;
case 'a':
ts = node; break;
case '$':
ts = "$"; break;
default:
ts = "";
} /* switch */
while ((*ts != EOS) && (t-exp < TEXTLEN-2))
*t++ = *ts++;
s++;
}
#ifdef ZAPTHISOUT /* can finish this later */
else if (*s == '%') {
switch (*(++s)) {
case 'f':
ts = from; break;
case 't':
ts = to; break;
case 'a':
ts = node; break;
case 'w':
ts = jweekday; break;
case 'd':
ts = jmonday; break;
case 'm':
ts = jmonth; break;
case 'y':
ts = jyear; break;
case 'h':
ts = jtime; break;
case '%':
ts = "%"; break;
default:
ts = "";
} /* switch */
while ((*ts != EOS) && (t-exp < TEXTLEN-2))
*t++ = *ts++;
s++;
}
#endif
else *t++ = *s++;
} /* while */
*t++ = '\n';
*t = EOS;
return(strdup(exp));
} /* expandattrib */
static char *scaninternet(BUFFER *msgbuf, MSG *message)
{
LINE *t;
static char buffer[128];
enum {IN_HEAD, IN_TEXT};
int scan;
if (arealist[area].netmail && (stricmp(message->header.from, "uucp") == 0)) {
/* message is from the uucp gateway */;
} else if (arealist[area].echomail) {
t = msgbuf->first;
while (t != NULL) {
if (strncmp(t->text, "\01UFGATE ", 8) == 0)
break; /* found marker */
t = t->next;
}
if (t == NULL) return NULL; /* not found */
} else return NULL; /* not a recognized message */
t = msgbuf->first;
scan = IN_HEAD;
buffer[0] = EOS;
while (t != NULL) {
if (scan == IN_HEAD) {
if (sscanf(t->text, "From: %127s", buffer) == 1)
break;
if ((t->text == NULL) || (*t->text == '\n')) /* empty line */
scan = IN_TEXT;
} /* might add heuristics to recognize signatures */
t = t->next;
} /* while */
if (buffer[0] == EOS) return NULL;
return buffer;
} /* scaninternet */
static void doquote(BOOLEAN otherarea) /* new version */
{
char origfr[TEXTLEN]; /* $f: quoted message from person */
char origto[TEXTLEN]; /* $t: quoted message to person */
char repdate[40]; /* $d: date of original message */
ADDRESS fromaddr;
int i;
char *qs;
LINE *t;
int link, oldup;
int curarea = area, newarea;
int tm;
char *internet = NULL;
if (areas < 2) otherarea = FALSE; /* avoid silly stuff */
if (otherarea) {
newarea = selectarea("SELECT DESTINATION AREA");
area = curarea; /* selectarea() might have changed it */
if (newarea == -1)
return;
} else newarea = area;
memset(&message.to,0, sizeof(message.to));
memset(&message.from,0,sizeof(message.from));
message.to.zone = message.from.zone = thisnode[arealist[newarea].aka].zone;
i = rm;
rm = quoteright; /* right margin for quoting */
readmsg(&message, message.header.msgnum);
rm = i;
internet = scaninternet(&msgbuf, &message); /* look for internet address */
if (otherarea) {
area = newarea;
link = oldup = 0;
message.header.board = CurBoard;
} else {
link = message.header.msgnum;
oldup = message.header.up;
} /* else */
tm = curmsg(CurBoard);
strcpy(origfr,message.header.from); /* original from & to */
strcpy(origto,message.header.to);
/* original post date */
strncpy(repdate, timedate(message.header.posttime, message.header.postdate, NO), sizeof(repdate));
if (internet != NULL) {
strncpy(message.header.to, "UUCP", sizeof(message.header.to));
memset(&message.to, 0, sizeof(message.to)); /* force lookup */
} else {
memcpy(message.header.to, message.header.from,sizeof(message.header.to));
message.to = message.from;
}
fromaddr = message.from; /* $a for netmail */
message.from = thisnode[arealist[newarea].aka];
if (message.from.domain != NULL)
message.from.domain = strdup(message.from.domain);
/* message.from.domain = NULL; */
#ifdef EIDS
memset(&message.eid,0,sizeof(message.eid));
#endif
memset(&message.msgid,0,sizeof(message.msgid));
message.header.msgnum = newmsgnum(); /* new message number */
memset(message.header.from,0,sizeof(message.header.from));
strncpy(message.header.from, username, sizeof(message.header.from));
timestr(message.header.posttime,message.header.postdate);
clear_attributes(&message.header); /* reset the bits */
message.header.reply = link;
message.header.up = oldup;
/* now scan the text and insert quote marks */
t = msgbuf.first;
/* memset(work,0,sizeof work); */
qs = expandquote(quotestr, origfr);
while (t != NULL) {
if (!shownotes && (*t->text == '\01')) { /* remove current hidden lines */
LINE *temp = t;
t = t->next; /* step to next line */
deleteline(&msgbuf,temp); /* and delete current line */
continue;
} /* if */
t->quote = 1;
if (t->text != NULL) {
char line[TEXTLEN]; /* temporary quoted line */
sprintf(line, " %s%s",qs,t->text); /* could also remove old quotes */
if (strchr(t->text, '\n') == NULL)
strcat(line, "\n");
ptrfree(t->text);
t->text = strdup(line);
assert(t->text);
} /* if */
t = t->next;
} /* while */
ptrfree(qs); /* quote string */
if ((attribline != NULL) && (*attribline != EOS)) {
char origin[30]; /* $a: node address of quoted person */
char *attr;
*origin = EOS; /* empty */
if (fromaddr.net != 0) {
strcpy(origin,formaddr(fromaddr,Z_O|N_A|P_O|D_O));
} /* if */
attr = expandattrib(attribline,origfr,origin,origto,repdate);
/* note: attr may be longer than screen line -- should be ok */
prependline("\n");
prependline(attr);
ptrfree(attr);
} /* if */
if (otherarea) {
char org[TEXTLEN];
sprintf(org, " * Moved from %s (%s) by %s\n",
arealist[curarea].tag,arealist[curarea].description,username);
prependline("\n");
prependline(org);
} /* if */
if (internet != NULL) {
char interaddr[140];
sprintf(interaddr, "To: %s\n", internet);
prependline("\n");
prependline(interaddr);
}
editheader();
if ((editmsg()) == SAVE) {
if (link != 0) {
MSGHEADER hlink;
readheader(link, &hlink);
hlink.up = message.header.msgnum;
writeheader(&hlink);
} /* if */
save(message);
} /* if */ /* else ABORT */
setcur(CurBoard,tm);
area = curarea;
} /* doquote */
void change()
{
LINE *t;
readmsg(&message, message.header.msgnum);
t = msgbuf.first;
while (t != NULL) {
if (!shownotes && (*t->text == '\01')) { /* remove current hidden lines */
LINE *temp = t;
t = t->next; /* step to next line */
deleteline(&msgbuf,temp); /* and delete current line */
} else {
t = t->next;
} /* else */
} /* while */
#ifdef EIDS
memset(&message.eid,0,sizeof(message.eid));
#endif
memset(&message.msgid,0,sizeof(message.msgid));
timestr(message.header.posttime,message.header.postdate);
/* probably shouldn't clear 'is_rcvd' bit because of MSGTOIDX.BBS */
message.header.bits.is_rcvd = message.header.bits.is_sent = 0;
if (arealist[area].echomail)
message.header.bits.is_echotr = 1;
if (arealist[area].netmail)
message.header.bits.is_transit = 1;
editheader();
if (editmsg() == SAVE)
writemsg(&message);
} /* change */
/*
* Show attributes that can be changed
*/
void show_attrib()
{
gotoxy(9, 5);
set_color(co_normal);
if (message.header.bits.is_priv)
set_color(co_hilite);
bputs("Private ");
set_color(co_normal);
if (message.header.bits.is_crash)
set_color(co_hilite);
bputs("Crash ");
set_color(co_normal);
if (message.header.bits.is_file)
set_color(co_hilite);
bputs("Attach ");
set_color(co_normal);
if (message.header.bits.is_kill)
set_color(co_hilite);
bputs("Kill/sent ");
set_color(co_normal);
gotoxy(1, 5);
bputs("Attrib: ");
} /* show_attrib */
int change_attrib()
{
int ch;
set_color(co_hilite);
gotoxy(1, 5);
video_update();
bputs("Attrib: ");
set_color(co_normal);
ch = getkey();
if (toupper((ch & 0xff)) == 'P')
message.header.bits.is_priv ^= 1;
if (toupper((ch & 0xff)) == 'C')
message.header.bits.is_crash ^= 1;
if (toupper((ch & 0xff)) == 'A')
message.header.bits.is_file ^= 1;
if (toupper((ch & 0xff)) == 'K')
message.header.bits.is_kill ^= 1;
return (ch);
} /* change_attrib */
int change_from()
{
int ch;
set_color(co_hilite);
gotoxy(1, 2);
bputs("From: ");
set_color(co_normal);
clreol();
ch = bgets(message.header.from, sizeof(message.header.from));
gotoxy(1, 2);
set_color(co_info);
bputs("From: ");
return (ch);
} /* change_from */
int change_orig()
{
int ch;
char tmp[INPLEN];
gotoxy(9 + strlen(message.header.from), 2);
set_color(co_hilite);
bputs(" of ");
set_color(co_normal);
strcpy(tmp,formaddr(message.from,Z_A|N_A|P_A|D_O));
ch = bgets(tmp, INPLEN);
message.from = parsenode(tmp);
gotoxy(9 + strlen(message.header.from), 2);
set_color(co_info);
bputs(" of ");
return (ch);
} /* change_orig */
int change_to()
{
int ch;
char tmp[sizeof(message.header.to)];
set_color(co_hilite);
gotoxy(1, 3);
bputs("To: ");
set_color(co_normal);
clreol();
memset(tmp,0,sizeof(tmp));
strncpy(tmp,message.header.to,sizeof(message.header.to));
ch = bgets(message.header.to, sizeof(message.header.to));
do_lookup = (strcmpl(tmp,message.header.to) != 0) ||
(message.to.node == 0);
gotoxy(1, 3);
set_color(co_info);
bputs("To: ");
if ((arealist[area].netmail) && do_lookup) {
message.to = lookup(message.header.to,fidolist);
if ((message.to.node == 0) && (userlist != NULL))
message.to = lookup(message.header.to,userlist);
} /* if */
return (ch);
} /* change_to */
int change_dest()
{
int ch;
char tmp[INPLEN];
gotoxy(9 + strlen(message.header.to), 3);
set_color(co_hilite);
bputs(" of ");
set_color(co_normal);
strcpy(tmp,formaddr(message.to,Z_A|N_A|P_A|D_O));
if (message.to.node == 0)
memset(tmp,0,sizeof(tmp));
ch = bgets(tmp, INPLEN);
message.to = parsenode(tmp);
if ((message.to.domain != NULL) && (message.from.domain == NULL)) {
if (thisnode[CurAKA].domain == NULL)
message.from.domain = strdup("Fidonet");
else
message.from.domain = strdup(thisnode[CurAKA].domain);
assert(message.from.domain);
} /* if */
gotoxy(9 + strlen(message.header.to), 3);
set_color(co_info);
bputs(" of ");
return (ch);
} /* change_dest */
static BOOLEAN exist(char *n)
{
FILE *f;
if ((f = fopen(n,"r")) != NULL) {
fclose(f);
return TRUE;
} else return FALSE;
} /* exist */
int change_subject()
{
int ch;
set_color(co_hilite);
gotoxy(1, 4);
if (message.header.bits.is_file)
bputs("Files: ");
else
bputs("Subj: ");
set_color(co_normal);
ch = bgets(message.header.subj, sizeof(message.header.subj));
if (strlen(message.header.subj) > 3) /* check if filename */
if ((message.header.subj[1] == ':') && (isalpha(message.header.subj[0]))
&& (message.header.subj[2] == '\\')) {
message.header.bits.is_file = 1; /* set file attach bit */
show_attrib();
} /* if */
gotoxy(1, 4);
set_color(co_info);
if (message.header.bits.is_file) {
char s[74], *f;
bputs("Files: ");
strcpy(s,message.header.subj);
for (f = strtok(s," \t"); f != NULL; f = strtok(NULL," \t")) {
if (exist(f)) {
set_color(co_info);
} else {
set_color(co_warn);
beep(0,0);
} /* else */
bprintf("%s ", f);
} /* for */
set_color(co_info);
} else
bputs("Subj: ");
return(ch);
} /* change_subject */
void editheader()
{
int field = 2;
int ch = 0;
set_color(co_info);
cls();
gotoxy(1, 2);
bputs("From: ");
bputs(message.header.from);
gotoxy(1, 3);
bputs("To: ");
gotoxy(1, 4);
if (message.header.bits.is_file)
bputs("Files: ");
else
bputs("Subj: ");
show_attrib();
gotoxy(1, 6);
bputs(
"______________________________________________________________________________"
);
gotoxy(1, 6);
set_color(co_hilite);
bputs(arealist[area].description);
set_color(co_normal);
while (ch != DONE) {
switch (field) {
case 0:
ch = change_from();
break;
case 1:
ch = change_orig();
break;
case 2:
ch = change_to();
break;
case 3:
ch = change_dest();
break;
case 4:
ch = change_subject();
break;
case 5:
ch = change_attrib();
show_attrib();
break;
} /* switch */
if (ch == UP) {
field--;
if (field < 0)
field = 5;
if ((field == 3) && !arealist[area].netmail)
field = 2;
if ((field == 1) && !arealist[area].netmail)
field = 0;
} /* if */
if ((ch == DOWN) || (ch == ENTER)) {
if ((field == 5) && (ch == ENTER))
break;
field++;
if (field > 5)
field = 0;
if ((field == 3) && !arealist[area].netmail)
field = 4;
if ((field == 1) && !arealist[area].netmail)
field = 2;
continue;
} /* if */
} /* while */
#ifdef EIDS
memset(&message.eid,0,sizeof(message.eid));
#endif
memset(&message.msgid,0,sizeof(message.msgid));
showheader(message);
} /* editheader */
/*
* Update the time and date fields of the message header
*/
void timestr(char *tim, char *dat)
{
struct tm *t;
time_t ltime;
time(<ime);
t = localtime(<ime);
sprintf(tim, "%02d:%02d", t->tm_hour, t->tm_min);
sprintf(dat, "%02d-%02d-%02d", t->tm_mon+1, t->tm_mday, t->tm_year);
} /* timestr */
void clear_attributes(MSGHEADER * h)
{
h->bits = arealist[area].msgbits; /* set defaults */
if (arealist[area].netmail) { /* now modify the bits */
h->bits.is_netm = 1;
h->bits.is_transit = 1;
h->bits.is_echotr = 0;
h->bits.is_local = 1; /* 28/09/90 */
} else {
h->bits.is_crash = 0;
h->bits.is_priv = 0;
h->bits.is_kill = 0;
h->bits.is_netm = 0;
h->bits.is_transit = 0;
if (arealist[area].echomail)
h->bits.is_echotr = 1;
else
h->bits.is_echotr = 0;
} /* else */
} /* clear_attributes */
void save(MSG message)
{
LINE *l;
char **name = NULL;
ADDRESS *address = NULL;
char buf[TEXTLEN];
char o[TEXTLEN];
char *a = NULL;
char *s = NULL;
int i = 0;
int j = 0;
/* write the original message */
writemsg(&message);
setcur(CurBoard,message.header.msgnum);
/* initialize stuff */
memset(buf,0,TEXTLEN);
memset(o,0,TEXTLEN);
/* check for a cc: */
l = msgbuf.first;
while ((l != NULL) && (*l->text == '\01'))
l = l->next;
if (l == NULL)
return;
s = l->text;
while (isspace(*s))
s++;
/* if no cc:, then return */
strcpy(buf,s);
strlwr(buf);
if (strncmp(buf,"cc:",3) != 0)
return;
name = (char **) calloc(1, sizeof(char **));
address = (ADDRESS *) calloc(1,sizeof(ADDRESS));
sprintf(o," * Original to %s @ %s\n",message.header.to,
formaddr(message.to,Z_A|N_A|P_O|D_O));
/* build the address list */
while ((l != NULL) && (l->text != NULL)) {
if (tolower(*s) == 'c') s = strchr(s,' ');
while (isspace(*s))
s++;
memset(buf,0,TEXTLEN);
strcpy(buf,s);
a = strchr(buf,'\n');
if (a != NULL)
*a = '\0';
a = strrchr(buf,' ');
if (a == NULL)
break;
else
a++;
if (isdigit(*a)) {
address[i] = parsenode(a);
*(a - 1) = '\0';
}
else {
address[i] = lookup(buf,fidolist);
if ((address[i].net == 0) && (userlist != NULL))
address[i] = lookup(buf,userlist);
}
name[i] = strdup(buf);
i++;
if ((address = (ADDRESS *) realloc(address,sizeof(ADDRESS) * (i+1))) == NULL)
return;
if ((name = (char **) realloc(name,sizeof(char **) * (i+1))) == NULL) {
ptrfree(address);
return;
}
l = l->next;
s = l->text;
}
if ((l = (LINE *) calloc(1,sizeof(LINE))) == NULL) {
ptrfree(name);
ptrfree(address);
return;
}
l->text = strdup("\n");
assert(l->text);
l->next = msgbuf.first;
l->next->prev = l;
l->prev = NULL;
msgbuf.first = l;
if ((l = (LINE *) calloc(1,sizeof(LINE))) == NULL) {
ptrfree(name);
ptrfree(address);
return;
}
l->text = strdup(o);
assert(l->text);
l->next = msgbuf.first;
l->next->prev = l;
l->prev = NULL;
msgbuf.first = l;
for (j = 0; j < i; j++) {
message.to = address[j];
#ifdef EIDS
memset(&message.eid,0,sizeof(message.eid));
#endif
memset(&message.msgid,0,sizeof(message.msgid));
message.header.bits.is_kill = 1;
memset(message.header.to,0,sizeof(message.header.to));
strncpy(message.header.to,name[j],sizeof(message.header.to));
ptrfree(name[j]);
message.header.msgnum = newmsgnum();
writemsg(&message);
setcur(CurBoard,message.header.msgnum);
}
ptrfree(name);
ptrfree(address);
} /* save */